<?php
/**
 * Created by PhpStorm.
 * User: 戎大富
 * Date: 2018/6/13
 * Time: 10:40
 */
namespace app\api\controller;
use think\Controller;
use think\Db;

class  Weixin extends Base  {
    // 定义配置项
    private $config=array(
        'APPID'              => 'wx0ae8c912db07c4dd', // 微信支付APPID.
        'MCHID'              => '1502805281', // 微信支付MCHID 商户收款账号
        'KEY'                => 'JD4sGRAmJSzlPYKdohaL561nGBOQW3ba', // 微信支付KEY
        'APPSECRET'          => '6a54b5e88c2dd87159bfeca466a9a770', // 公众帐号secert (公众号支付专用)
        'NOTIFY_URL'         => 'http://heart.xuanwumobile.com/api/Weixin/huidiao', // 接收支付状态的连接

    );
    public $body;//描述
    public $total_fee;//喵额
    public $out_trade_no;//订单号

    // 构造函数
    public function __construct($config=null){
        // 如果配置项为空 则直接返回
        if (!empty($config)) {
            $this->config=$config;
        }
    }
    /***
     * @param $code
     * @param string $msg
     * 错误返回信息
     */
    protected function apiError($code, $msg = '')
    {
        if (!$msg) {
            $info['msg'] = $this->_error[$code]['msg'];
        } else {
            $info['msg'] = $msg;
        }
        $info['status'] = $code;
        $returnInfo = json_encode($info, JSON_UNESCAPED_UNICODE);
        echo $returnInfo;
        exit();
    }
    /**
     * 微信支付接口
     * @return string
     * classroom_id：课程ID,当type为1时，传此参数
     * user_id：用户ID,
     * type：1 课程购买  2 捐赠  3 打赏
     * price：打赏或捐赠的价格，当type为2或者3时传
     * activity_id：捐赠的活动ID，当type为2时，传此值
     */
    public function WeChatApi(){

        extract(input());
        $params = input('param.');
        $res = $this->checkAll($params['user_id'], $params['time'], $params['value'], $params['reqKey']);
        if($res == 112) {
            return json(['status' => 301, 'msg' => $this->otherLogin]);
        }elseif($res == 110){
            return json(['status' => 302, 'msg' => $this->frost]);
        }
        if($params['type']==1){
            //研学活动
//            $result = Db::table('up_notice_order')->where('notice_id',$params['id'])->find();
            $result = Db::table('up_notice_order')->alias('a')
                ->join('up_notice un','un.n_id = a.n_id')
                ->where('notice_id',$params['id'])->field('a.*,un.n_money')->find();
            $this->body = '橡榛教育';
            $this->total_fee = $result['n_money'] * 100;
            $this->out_trade_no = $result['notice_num'];
            $order = array();
            $order['body'] = $this->body;//描述
            $order['total_fee'] = $this->total_fee;//订单喵额
            $order['out_trade_no'] = $this->out_trade_no;//订单号
            $order['product_id'] = '';//产品ID
            $order['trade_type'] = 'APP';//类型
            $respont = $this->WeChatPayReady($order);
            return json_encode(['status'=>200,'msg'=>$respont]);
        }else{
            //查询这个订单详情
            $info = Db::table('up_order')->where('order_id',$params['id'])->find();
            if($info['order_id']==''){
                return json_encode(['status' => 0, 'msg' => '订单不存在']);
            }

            //查询订单里面每个商品的详情
            $goodInfo  = Db::table('up_order_info')->where('oi_order_id',$params['id'])->select();
            //判断库存数量
            foreach ($goodInfo as $key=>$vo){
                $result = Db::table('up_goods')->where('good_id',$vo['oi_good_id'])->find();
                if($vo['oi_type']==2){//图书
                    if($vo['oi_num']>$result['good_stock']){
                        return json_encode(['status' => 0, 'msg' => '抱歉,您选购的'.$result['good_name'].'数量大于剩余库存数量,请重新选择']);
                    }
                }elseif ($vo['oi_type']==1){//非图书
                    $result1 = Db::table('up_good_spec')->where('spec_id',$vo['oi_spec_id'])->find();
                    if($vo['oi_num']>$result1['spec_stock']){
                        return json_encode(['status' => 0, 'msg' => '抱歉,您选购的'.$result['good_name'].'商品暂时无货']);
                    }
                }
            }
//        $info['order_user_pay'] = 0.01;
            if($info['order_hh_payment']==3){//人民币支付

                $this->body = '橡榛教育';
                $this->total_fee = $info['order_user_pay'] * 100;
                $this->out_trade_no = $info['order_number'];
                $order = array();
                $order['body'] = $this->body;//描述
                $order['total_fee'] = $this->total_fee;//订单喵额
                $order['out_trade_no'] = $this->out_trade_no;//订单号
                $order['product_id'] = '';//产品ID
                $order['trade_type'] = 'APP';//类型
                $respont = $this->WeChatPayReady($order);
                return json_encode(['status'=>200,'msg'=>$respont]);


            }elseif ($info['order_hh_payment']==2){//喵币支付
                //查询喵币兑换的次数
                $num = Db::table('up_convert')->where('convert_id',1)->find();
                $start = date('Y-m-d H:i:s',strtotime('-24 hours'));
                $end = date('Y-m-d H:i:s',time());
                //查询当前时间24小时之前购物的商品记录
                $where['order_time'] = array('between',array($start,$end));
                $where['order_userid'] = $user_id;
                $where['order_hh_payment'] = array('IN','1,2');
                $where['order_status'] = array('IN','2,3,4');
                $count = Db::table('up_order')->where($where)->count();
                if($count>=$num['convert_num']){
                    return json_encode(['status'=>10,'msg'=>"规定时间内兑换喵币次数超过默认限制"]);
                }
                //查询这个用户的喵币
                $user_integral = Db::table('up_u_user')->where('user_id',$user_id)->value('user_integral');
                if($info['order_j_glod']>$user_integral){//证明购买花费的喵币大于用户账号的喵币数量
                    return json_encode(['status'=>100,'msg'=>"喵币不足不能购买"]);
                }else{
                    $this->body = '橡榛教育';
                    $this->total_fee = $info['order_user_pay'] * 100;
                    $this->out_trade_no = $info['order_number'];
                    $order = array();
                    $order['body'] = $this->body;//描述
                    $order['total_fee'] = $this->total_fee;//订单喵额
                    $order['out_trade_no'] = $this->out_trade_no;//订单号
                    $order['product_id'] = '';//产品ID
                    $order['trade_type'] = 'APP';//类型
                    $respont = $this->WeChatPayReady($order);
                    return json_encode(['status'=>200,'msg'=>$respont]);
                }
            }elseif ($info['order_hh_payment']==1){//混合支付

                $num = Db::table('up_convert')->where('convert_id',1)->find();
                $start = date('Y-m-d H:i:s',strtotime('-24 hours'));
                $end = date('Y-m-d H:i:s',time());
                //查询当前时间24小时之前购物的商品记录
                $where['order_time'] = array('between',array($start,$end));
                $where['order_userid'] = $user_id;
                $where['order_hh_payment'] = array('IN','1,2');
                $where['order_status'] = array('IN','2,3,4');
                $count = Db::table('up_order')->where($where)->count();
                if($count>=$num['convert_num']){
                    return json_encode(['status'=>0,'msg'=>"规定时间内兑换喵币次数超过默认限制"]);
                }
                //查询这个用户的喵币
                $user_integral = Db::table('up_u_user')->where('user_id',$user_id)->value('user_integral');
                if($info['order_j_glod']>$user_integral){//证明购买花费的喵币大于用户账号的喵币数量
                    return json_encode(['status'=>100,'msg'=>"喵币不足不能购买"]);
                }
                $this->body = '橡榛教育';
                $this->total_fee = $info['order_user_pay'] * 100;
                $this->out_trade_no = $info['order_number'];
                $order = array();
                $order['body'] = $this->body;//描述
                $order['total_fee'] = $this->total_fee;//订单喵额
                $order['out_trade_no'] = $this->out_trade_no;//订单号
                $order['product_id'] = '';//产品ID
                $order['trade_type'] = 'APP';//类型
                $respont = $this->WeChatPayReady($order);
                return json_encode(['status'=>200,'msg'=>$respont]);
            }
        }
//        $user_id = 125;

    }

    /**
     * 统一下单
     * @param  array $order 订单 必须包含支付所需要的参数 body(产品描述)、total_fee(订单喵额)、out_trade_no(订单号)、product_id(产品id)、trade_type(类型：JSAPI，NATIVE，APP)
     */
    public function WeChatPayReady($order,$type=null){
        // 获取配置项
        $weixinpay_config=$this->config;
        $config=array(
            'appid'=>$weixinpay_config['APPID'],
            'mch_id'=>$weixinpay_config['MCHID'],
            'nonce_str'=>'test',
            'spbill_create_ip'=>$_SERVER['REMOTE_ADDR'],
            'notify_url'=>$weixinpay_config['NOTIFY_URL']
        );
        if(!empty($type)){
            $config['notify_url']='http://heart.xuanwumobile.com/api/Weixin/huidiao';
        }
        // 合并配置数据和订单数据
        $data=array_merge($order,$config);

        // 生成签名
        $sign=$this->makeSign($data);
        $data['sign']=$sign;
        $xml=$this->toXml($data);
//        <xml>
//            <body><![CDATA[南丁格尔课程购买]]></body>
//            <total_fee>0</total_fee>
//            <out_trade_no>15359632423617767</out_trade_no>
//            <product_id><![CDATA[]]></product_id>
//            <trade_type><![CDATA[APP]]></trade_type>
//            <appid><![CDATA[wx5518b83be52f8d41]]></appid>
//            <mch_id>1513192391</mch_id>
//            <nonce_str><![CDATA[test]]></nonce_str>
//            <spbill_create_ip><![CDATA[127.0.0.1]]></spbill_create_ip>
//            <notify_url><![CDATA[http://south.xuanwumobile.com/api/Weixin/huidiao]]></notify_url>
//            <sign><![CDATA[7203312FA0E1F814BEA0674495BBF9CA]]></sign>
//        </xml>
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';//接收xml数据的文件
        $header[] = "Content-type: text/xml";//定义content-type为xml,注意是数组
        $ch = curl_init ($url);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);//严格校验
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        $response = curl_exec($ch);
        if(curl_errno($ch)){
            print curl_error($ch);
        }
        curl_close($ch);
        $result=$this->toArray($response);
        $result['sign']=$sign;
        $result['nonce_str']='test';
        $result2 = $this->getOrder($result['prepay_id']);
        return $result2;///
    }
    
    /**
     * 获取时间
     * @return array
     */
    public function getDateBytimeDate($string){
        $replacement = '-';
        $replacement2 = ':';
        $a = substr_replace($string, $replacement, 4, 0);
        $b = substr_replace($a, $replacement, 7, 0);
        $c = substr_replace($b, ' ', 10, 0);
        $d = substr_replace($c, $replacement2, 13, 0);
        $e = substr_replace($d, $replacement2, 16, 0);
        return $e;
    }
    /**
     * 回调
     * @return string
     */
    public function write_admin_log($data)
    {
        $file_name = 'file/log/' . date('Ymd', time()) . '.txt';
        if (is_array($data)) {
            $data_str = implode(' | ', $data);
        } else {
            $data_str = $data;
        }
        file_put_contents($file_name, $data_str . "\r\n\r\n", FILE_APPEND);
    }
    /**
     * 验证
     * @return array 返回数组格式的notify数据
     */
    public function huidiao(){
        // 获取xml
        $xml=file_get_contents('php://input', 'r');
        // 转成php数组
        $getInfo=$this->toArray($xml);
//        $this->write_admin_log($getInfo);
        // 保存原sign
        $data_sign=$getInfo['sign'];
        // sign不参与签名
        unset($getInfo['sign']);
        $sign=$this->makeSign($getInfo);
        // 判断签名是否正确  判断支付状态
        if ($sign===$data_sign && $getInfo['return_code']=='SUCCESS' && $getInfo['result_code']=='SUCCESS') {
            Db::startTrans();
            try{
                $num = $getInfo['out_trade_no'];
                $dataOrder = array();
                $dataOrder['order_paytime'] = $this->getDateBytimeDate("{$getInfo['time_end']}");//付款时间
                $dataAll = Db::table('up_notice_order')->where('notice_num',$num)->find();
                if($dataAll['notice_id']!=''){
                    //研学活动
                    $haveC = Db::table('up_studies')->where('st_id', $dataAll['studies_id'])->find();
                    if($haveC['st_pay_status'] != 1){
                        die('success');
                    }
                    Db::table('up_notice')->where('n_id', $dataAll['n_id'])->setInc('n_num_already');
                    $res1 = Db::table('up_notice')->where('n_id', $dataAll['n_id'])->find();
                    $data2['st_pay_status'] = 2;
                    $data2['st_pay_time'] = date('Y-m-d H:i:s',time());
                    $data2['st_pay_type'] = 2;
                    $data2['st_pay_num'] = $num;
                    $res2 = Db::table('up_studies')->where('st_id', $dataAll['studies_id'])->update($data2);
                    $data1['notice_status'] = 2;
                    $data1['notice_pay_time'] = date('Y-m-d H:i:s',time());
                    $res3 = Db::table('up_notice_order')->where('notice_id', $dataAll['notice_id'])->update($data1);
                    //TODO  插入财务表
                    $resultAll1['revenue_name'] = $dataAll['notice_num'];
                    $resultAll1['revenue_time'] = date('Y-m-d H:i:s',time());
                    $resultAll1['revenue_type'] = 2;
                    $resultAll1['revenue_status'] = 1;
                    $resultAll1['revenue_price'] = $res1['n_money'];
                    $resultAll1['revenue_gl_id'] = $res1['n_id'];
                    Db::table('up_revenue')->insert($resultAll1);

                    Db::commit();
                    $result = true;
                }else{
                    //商城
                    $dataOrder['order_status'] = 2;
                    $info = Db::table('up_order')->where('order_number',$num)->find();

                    if($info['order_id']!=''){
                        if($info['order_status'] != 1){
                            die('success');
                        }
                        $aa = Db::table('up_order')->where('order_number',$num)->update($dataOrder);
                        $All = Db::table('up_order_info')->where('oi_order_id',$info['order_id'])->select();
                        if($info['order_hh_payment']==1){//混合支付
                            //修改用户账户的余额
                            Db::table('up_u_user')->where('user_id',$info['order_userid'])->setDec('user_integral',$info['order_j_glod']);

                            $resultAll['glod_user_id'] =$info['order_userid'];
                            $resultAll['glod_status'] =5;
                            $resultAll['glod_type'] =1;
                            $resultAll['glod_money'] =$info['order_j_glod'];
                            $resultAll['glod_time'] =date('Y-m-d H:i:s',time());
                            Db::table('up_glod')->insertGetId($resultAll);

                            foreach ($All as $key=>$vo){//循环减库存
                                if($vo['oi_type']==1){//人民币
                                    Db::table('up_good_spec')->where('spec_id',$vo['oi_spec_id'])->setDec('spec_stock',$vo['oi_num']);
                                    Db::table('up_goods')->where('good_id',$vo['oi_good_id'])->setDec('good_stock',$vo['oi_num']);

                                    //加销量
                                    Db::table('up_goods')->where('good_id',$vo['oi_good_id'])->setInc('good_sales_num',$vo['oi_num']);
                                }elseif ($vo['oi_type']==2){//喵币
                                    Db::table('up_goods')->where('good_id',$vo['oi_good_id'])->setDec('good_stock',$vo['oi_num']);

                                    //加销量
                                    Db::table('up_goods')->where('good_id',$vo['oi_good_id'])->setInc('good_sales_num',$vo['oi_num']);
                                }
                            }
                            $this->getHonorForEvery($info['order_userid'],10);

                        }elseif ($info['order_hh_payment']==3){
                            //人民币支付
                            foreach ($All as $key=>$vo){//循环减库存
                                Db::table('up_good_spec')->where('spec_id',$vo['oi_spec_id'])->setDec('spec_stock',$vo['oi_num']);
                                //加销量
                                Db::table('up_goods')->where('good_id',$vo['oi_good_id'])->setInc('good_sales_num',$vo['oi_num']);
                            }
                            if($info['order_is_coupon']==1){
                                $this->getHonorForEvery($info['order_userid'],10);
                            }
                        }elseif ($info['order_hh_payment']==2){//喵币支付
                            //修改用户账户的余额
                            Db::table('up_u_user')->where('user_id',$info['order_userid'])->setDec('user_integral',$info['order_j_glod']);
                            $resultAll['glod_user_id'] =$info['order_userid'];
                            $resultAll['glod_status'] =5;
                            $resultAll['glod_type'] =1;
                            $resultAll['glod_money'] =$info['order_j_glod'];
                            $resultAll['glod_time'] =date('Y-m-d H:i:s',time());
                            Db::table('up_glod')->insertGetId($resultAll);
                            foreach ($All as $key=>$vo){
                                Db::table('up_goods')->where('good_id',$vo['oi_good_id'])->setDec('good_stock',$vo['oi_num']);
                                //加销量
                                Db::table('up_goods')->where('good_id',$vo['oi_good_id'])->setInc('good_sales_num',$vo['oi_num']);
                            }
                            $this->getHonorForEvery($info['order_userid'],10);

                        }
//                if($info['order_is_coupon']==1){
//                    Db::table('up_my_coupon')->where('mc_id',$info['order_my_coupon'])->setField('mc_status',2);
//                }
                        $resultAll1['revenue_name'] = $num;
                        $resultAll1['revenue_time'] = date('Y-m-d H:i:s',time());
                        $resultAll1['revenue_type'] = 1;
                        $resultAll1['revenue_status'] = 1;
                        $resultAll1['revenue_price'] = $info['order_user_pay'];
                        $resultAll1['revenue_glod'] = $info['order_j_glod'];
                        $resultAll1['revenue_gl_id'] = $info['order_id'];
                        Db::table('up_revenue')->insert($resultAll1);
                        $result=$getInfo;
                    }else{
                        $result=false;
                    }
                    Db::commit();
                }
            }catch(\Exception $e){
                Db::rollback();//回滚
                $result = false;
            }
        }else{
            $result=false;
        }
        // 返回状态给微信服务器----------------
        if ($result) {
            $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        }else{
            $str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>';
        }
        echo $str;
        exit();
        return $result;
    }
    
    /**
     * 生成签名
     * @return 签名，本函数不覆盖sign成员变量，如要设置签名需要调用SetSign方法赋值
     */
    public function makeSign($data){
        // 去空
        $data=array_filter($data);
        //签名步骤一：按字典序排序参数
        ksort($data);
        $string_a=http_build_query($data);
        $string_a=urldecode($string_a);
        //签名步骤二：在string后加入KEY
        $config=$this->config;
        $string_sign_temp=$string_a."&key=".$config['KEY'];
        //签名步骤三：MD5加密
        $sign = md5($string_sign_temp);
        // 签名步骤四：所有字符转为大写
        $result=strtoupper($sign);
        return $result;
    }

    /**
     * 将xml转为array
     * @param  string $xml xml字符串
     * @return array       转换得到的数组
     */
    public function toArray($xml){
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $result= json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $result;
    }
    
    /**
     * 输出xml字符
     * @throws WxPayException
     **/
    public function toXml($data){
        //var_dump($data);
        if(!is_array($data) || count($data) <= 0){
            //throw new WxPayException("数组数据异常！");
        }
        $xml = "<xml>";
        foreach ($data as $key=>$val){
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml;
    }

    
    //数组转xml
    function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key=>$val)
        {
            if (is_numeric($val))
            {
                $xml.="<".$key.">".$val."</".$key.">";

            }
            else
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
        }
        $xml.="</xml>";
        return $xml;
    }

    //post https请求，CURLOPT_POSTFIELDS xml格式
    public function postXmlCurl($xml,$url,$second=30)
    {
        //初始化curl
        $ch = curl_init();
        //超时时间
        curl_setopt($ch,CURLOPT_TIMEOUT,$second);
        //这里设置代理，如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行curl
        $data = curl_exec($ch);
        //返回结果
        if($data)
        {
            curl_close($ch);
            return $data;
        }
        else
        {
            $error = curl_errno($ch);
            echo "curl出错，错误码:$error"."<br>";
            echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
            curl_close($ch);
            return false;
        }
    }
    
    //获取指定长度的随机字符串
    function getRandChar($length){
        $str = null;
        $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
        $max = strlen($strPol)-1;

        for($i=0;$i<$length;$i++){
            $str.=$strPol[rand(0,$max)];//rand($min,$max)生成介于min和max两个数之间的一个随机整数
        }

        return $str;
    }
    
    //执行第二次签名，才能返回给客户端使用
    public function getOrder($prepayId){
        $data["appid"] = $this->config["APPID"];
        $data["noncestr"] = $this->getRandChar(32);
        $data["package"] = "Sign=WXPay";
        $data["partnerid"] = $this->config['MCHID'];
        $data["prepayid"] = $prepayId;
        $data["timestamp"] = time();
        $s = $this->makeSign($data, false);
        $data["sign"] = $s;
        
        return $data;
    }
    
    /**
     * 获取当前服务器IP
     * @return string
     */
    public  function get_client_ip()
    {
        if ($_SERVER['REMOTE_ADDR']) {
            $cip = $_SERVER['REMOTE_ADDR'];
        } elseif (getenv("REMOTE_ADDR")) {
            $cip = getenv("REMOTE_ADDR");
        } elseif (getenv("HTTP_CLIENT_IP")) {
            $cip = getenv("HTTP_CLIENT_IP");
        } else {
            $cip = "unknown";
        }
        return $cip;
    }
    


}